<?php

declare(strict_types=1);
/**
 * @author chenshubo
 * 数据库模型基类
 */
namespace App\Model;

use Hyperf\DbConnection\Db;
use Hyperf\DbConnection\Model\Model;

class BaseModel extends Model
{
    public $timestamps = false;
    protected static $instance;

    /**
     * get instance
     * @access   public
     * @return   static
     */
    public static function instance()
    {
        $class_name = get_called_class();
    
        if (empty(self::$instance[$class_name])) {
            self::$instance[$class_name] = new static();
        }
        return self::$instance[$class_name];
    }
    
    /**
     * 获取单行数据
     * @param array $where
     */
    public function info( $where = [] ) 
    {
        
        $info = $this->_dealWhere($where)->first();
        if( empty($info) ) {
            return [];
        }
        
        return $info->toArray();
    }
    
    /**
    * 获取多条数据
    * @param    array  $where
    * @access   public
    * @return   array
    */
    public function lists($where = [])
    {
        $lists = $this->_dealWhere($where)->get();
        
        if (empty($lists)) {
            return [];
        }
        
        return $lists->toArray();
    }
    
    /**
     * 获取N行数据
     * @param array $where
     */
    public function rows( $where = [], $select = ['*'] )
    {        
        $query = $this->_dealWhere($where);
        return $query->select($select)->get()->toArray();
    }
    

    /**
     * 
     * @param    array  $where
     * @param    int    $limit
     * @param    int    $page
     * @access   public
     * @return   array
     */
   public function listPages($where = [], $limit = 20, $page = 1)
    {
        $db = $this->_dealWhere($where);
        
        $offset = $limit * ($page - 1);
        $offset < 0 && $offset = 0;
        $limit <= 0 && $limit = 20;
        
        $db->offset($offset);
        $db->limit($limit);
        
        $lists  =  $db->get();
        
        if (empty($lists)) {
            return [];
        }
        
        return $lists->toArray();
    }
    
    /**
     * 处理where 条件
     */
    public function _dealWhere( $params = [] ) 
    {
        $db = self::query();
        if(isset($params['_fields_'])){
            if(is_array($params['_fields_'])){
                $db->select($params['_fields_']);
            }else{
                $db->select(explode(',',$params['_fields_']));
            }
            unset($params['_fields_']);
        }
        if(isset($params['_limit_'])){
            if (is_array($params['_limit_']) && isset($params['_limit_'][0]) && $params['_limit_'][1]) {
                $db->offset($params['_limit_'][0]);
                $db->limit($params['_limit_'][1]);
            } else {
                $limit= explode(',', $limit);
                $db->offset($limit[0]);
                $db->limit($limit[1]);
            }
            unset($params['_limit_']);
        }
        //group
        if( isset($params['_group_']) ) {
            $db->groupBy($params['_group_']);
            unset($params['_group_']);
        }
        
        //order by
        if( isset($params['_order_']) ) {
            if (is_array($params['_order_'])) {
                foreach ($params['_order_'] as $key => $value) {
                    $db->orderBy($key,$value);
                }
            } else {
                $orderby= explode(',', $params['_order_']);
                foreach ($orderby as $key => $value) {
                    $order= explode(' ', $value);
                    $db->orderBy($order[0],$order[1]);
                }
               
            }
            unset($params['_order_']);
        }
        if(!empty($params)){
            foreach ($params as $key => $value) {
                if(is_array($value)&&$value[1]=='in'){
                    $db->whereIn($value[0],$value[2]);
                    unset($params[$key]);
                }
                if(is_array($value)&&$value[1]=='notin'){
                    $db->whereNotIn($value[0],$value[2]);
                    unset($params[$key]);
                }
                if(is_array($value)&&$value[1]=='between'){
                    $db->whereBetween($value[0],$value[2]);
                    unset($params[$key]);
                }
                if(is_array($value)&&$value[1]=='notbetween'){
                    $db->whereNotBetween($value[0],$value[2]);
                    unset($params[$key]);
                }
            }
            if(!empty($params)){                
                $db->where($params);
            }
        }
        return $db;
    }
    
    /**
    * 计算数据行数
    * @param    array  $where
    * @access   public
    * @return   int
    */
    public function countNum($where = null)
    {
        return $this->_dealWhere($where)->count();
    }
    
    /**
     * 写入单行数据
     * @param array $data
     */
    public function add( $data = [] ) 
    {
        if( empty($data) ) {
            return false;
        }
        if(config('sid')){
            $data['sid']=config('sid');
        }
        return $this->insertGetId($data);
    }
    
    /**
     * 写入多行单行数据
     * @param array $data
     */
    public function addMore( $data = [] )
    {
        if( empty($data) ) {
            return false;
        }
        
        return $this->insert($data);
    }
    
    /**
     * 写入单行数据
     * @param array $where
     */
    public function edit( $where = [] ,$data = [] )
    {
        if( empty($where) || empty($data) ) {
            return false;
        }
    
        return $this->where($where)->update($data);
    }

    /**
     * 删除数据
     * @param array $where
     */
    public function del( $where = [] )
    {
        if( empty($where) ) {
            return false;
        }
    
        return $this->_dealWhere($where)->delete();
    }
    
    /**
     * 开启事务
     */
    public function startTrans()
    {
        Db::beginTransaction();
    }
    
    /**
     * 提交事务
     */
    public function commit()
    {
        Db::commit();
    }
    
    /**
     * 回滚事务
     */
    public function rollback()
    {
        Db::rollBack();
    }
}
